package com.mini.grpc.examples.helloworld;

import com.mini.grpc.server.Server;
import com.mini.grpc.server.ServerBuilder;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

/**
 * HelloWorld gRPC 服务端
 * 演示如何启动和管理 gRPC 服务
 */
public class HelloWorldServer {
    
    private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName());
    private static final int DEFAULT_PORT = 50051;
    
    private Server server;
    private final int port;
    
    /**
     * 使用默认端口创建服务端
     */
    public HelloWorldServer() {
        this(DEFAULT_PORT);
    }
    
    /**
     * 使用指定端口创建服务端
     * 
     * @param port 服务端口
     */
    public HelloWorldServer(int port) {
        this.port = port;
    }
    
    /**
     * 启动服务端
     * 
     * @throws IOException 如果启动失败
     */
    public void start() throws IOException {
        logger.info("正在启动 gRPC 服务端...");
        
        // 创建服务实现
        HelloWorldServiceImpl serviceImpl = new HelloWorldServiceImpl();
        
        // 构建并启动服务端
        server = ServerBuilder.forPort(port)
            .addService(serviceImpl.bindService())
            .build()
            .start();
        
        logger.info(String.format("✅ gRPC 服务端已启动，监听端口: %d", port));
        logger.info("服务端提供以下服务:");
        logger.info("  - sayHello: 一元调用示例");
        logger.info("  - sayHelloServerStream: 服务端流式调用示例");
        logger.info("  - sayHelloClientStream: 客户端流式调用示例");
        logger.info("  - sayHelloBidiStream: 双向流式调用示例");
        
        // 添加关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            logger.info("*** 检测到JVM关闭信号，正在关闭gRPC服务端 ***");
            try {
                HelloWorldServer.this.stop();
            } catch (InterruptedException e) {
                logger.warning("服务端关闭过程被中断: " + e.getMessage());
                Thread.currentThread().interrupt();
            }
            logger.info("*** gRPC服务端已完全关闭 ***");
        }));
    }
    
    /**
     * 停止服务端
     * 
     * @throws InterruptedException 如果等待过程被中断
     */
    public void stop() throws InterruptedException {
        if (server != null) {
            logger.info("正在关闭gRPC服务端...");
            
            // 优雅关闭，等待30秒
            server.shutdown();
            if (!server.awaitTermination(30, TimeUnit.SECONDS)) {
                logger.warning("服务端未能在30秒内优雅关闭，强制关闭");
                server.shutdownNow();
                
                // 再等待5秒确保完全关闭
                if (!server.awaitTermination(5, TimeUnit.SECONDS)) {
                    logger.severe("服务端强制关闭失败");
                }
            }
            
            logger.info("gRPC服务端已关闭");
        }
    }
    
    /**
     * 阻塞等待直到服务端终止
     * 
     * @throws InterruptedException 如果等待过程被中断
     */
    public void blockUntilShutdown() throws InterruptedException {
        if (server != null) {
            logger.info("服务端正在运行，按 Ctrl+C 停止服务");
            server.awaitTermination();
        }
    }
    
    /**
     * 检查服务端是否正在运行
     * 
     * @return 如果服务端正在运行返回true
     */
    public boolean isRunning() {
        return server != null && !server.isShutdown();
    }
    
    /**
     * 获取服务端监听的端口
     * 
     * @return 端口号
     */
    public int getPort() {
        return port;
    }
    
    /**
     * 主方法 - 启动服务端
     * 
     * @param args 命令行参数，可选的端口号
     */
    public static void main(String[] args) {
        int port = DEFAULT_PORT;
        
        // 解析命令行参数
        if (args.length > 0) {
            try {
                port = Integer.parseInt(args[0]);
                if (port < 1 || port > 65535) {
                    throw new NumberFormatException("端口号必须在1-65535之间");
                }
            } catch (NumberFormatException e) {
                logger.severe("无效的端口号: " + args[0] + ", 使用默认端口: " + DEFAULT_PORT);
                port = DEFAULT_PORT;
            }
        }
        
        final HelloWorldServer server = new HelloWorldServer(port);
        
        try {
            // 启动服务端
            server.start();
            
            // 阻塞等待
            server.blockUntilShutdown();
            
        } catch (IOException e) {
            logger.severe("服务端启动失败: " + e.getMessage());
            e.printStackTrace();
            System.exit(1);
        } catch (InterruptedException e) {
            logger.info("服务端被中断");
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            logger.severe("服务端运行时发生未知错误: " + e.getMessage());
            e.printStackTrace();
            System.exit(1);
        }
    }
} 